package com.jlstu.daijia.common.login;

import com.jlstu.daijia.common.constant.RedisConstant;
import com.jlstu.daijia.common.execption.GuiguException;
import com.jlstu.daijia.common.result.ResultCodeEnum;
import com.jlstu.daijia.common.util.AuthContextHolder;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 监控需要登录才能访问的方法
 * 使用AOP切面编程实现，对标注了@GuiguLogin注解的方法进行拦截，进行登录验证
 */
@Aspect
@Component
public class GuiguLoginAspect {

    /**
     * Token的HTTP头部字段名称
     */
    private static final String TOKEN_HEADER = "token";

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 对标注了@GuiguLogin注解的方法进行拦截
     * 验证用户是否登录，未登录则抛出异常
     *
     * @param joinPoint 切点，包含被拦截方法的信息
     * @return 被拦截方法的返回值
     * @throws Throwable 被拦截方法抛出的任何异常
     */
    @Around("execution(* com.jlstu.daijia.*.controller.*.*(..)) && @annotation(com.jlstu.daijia.common.login.GuiguLogin)")
    public Object login(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = getHttpServletRequest();
        String token = request.getHeader(TOKEN_HEADER);

        // 检查Token是否存在
        if (!StringUtils.hasText(token)) {
            throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
        }

        // 从Redis中获取用户ID
        String customerId = redisTemplate.opsForValue().get(RedisConstant.USER_LOGIN_KEY_PREFIX + token);
        // 如果用户ID存在，则设置到AuthContextHolder中
        if (StringUtils.hasText(customerId)) {
            AuthContextHolder.setUserId(Long.parseLong(customerId));
        }

        // 继续执行被拦截的方法
        return joinPoint.proceed();
    }

    /**
     * 获取当前HTTP请求
     *
     * @return 当前的HTTP请求对象
     * @throws IllegalStateException 如果当前线程没有绑定HTTP请求
     */
    private HttpServletRequest getHttpServletRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes instanceof ServletRequestAttributes) {
            return ((ServletRequestAttributes) requestAttributes).getRequest();
        }
        throw new IllegalStateException("No HttpServletRequest found");
    }

    public static void main(String[] args) {
        long l = Long.parseLong("1");
        System.out.println(l);
    }
}
